# import torch
# import torch_geometric
# from torch_geometric.data import Data
# import networkx as nx
# import matplotlib.pyplot as plt
from torch_geometric.utils import to_networkx
# import pandas as pd
#
# # 读取 Excel 文件并选择指定的 sheet
# df = pd.read_excel(r"water_tu/data/20231128HESI-122_001.xlsx", sheet_name="Result")
#
# # 选择前100条数据进行分析
# df = df.head(100)
#
# # 提取特征，假设前几列为元素数量特征，其他为属性特征
# element_features = df[['C', 'H', 'O', 'N', 'C13', 'S', 'P', 'Cl']].values
# additional_features = df[['O/C', 'N/C', 'P/C', 'S/C', 'H/C', 'AImod']].values
#
# # 将所有特征组合成节点特征
# node_features = torch.tensor(element_features, dtype=torch.float)
#
# # 定义边关系，例如基于 O/C 比例差值，定义邻居
# edge_index = []
# threshold = 0.1  # 定义一个阈值用于确定是否连边
# for i in range(len(node_features)):
#     for j in range(i + 1, len(node_features)):
#         if abs(df['O/C'].iloc[i] - df['O/C'].iloc[j]) < threshold:
#             edge_index.append([i, j])
#             edge_index.append([j, i])
#
# edge_index = torch.tensor(edge_index, dtype=torch.long).t().contiguous()
#
# # 构建图数据结构
# data = Data(x=node_features, edge_index=edge_index)
#
# # 将图数据转换为 NetworkX 图以进行可视化
# G = to_networkx(data, node_attrs=['x'], to_undirected=True)
#
# # 定义节点布局方式，这里选择 spring_layout 来自动调整节点位置
# pos = nx.spring_layout(G, seed=42)  # 设置 seed 保证布局稳定
#
# # 可视化图结构
# plt.figure(figsize=(12, 12))
#
# # 绘制节点，节点大小可以根据某种特征调整，例如 Intensity
# node_labels = {i: round(df['O/C'].iloc[i], 2) for i in range(len(df))}
# nx.draw_networkx_nodes(G, pos, node_color='skyblue', node_size=300)
#
# # 绘制节点标签
# nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=8)
#
# # 绘制边
# nx.draw_networkx_edges(G, pos, edge_color='gray')
#
# # 显示图形
# plt.title("Graph Visualization of Mass Spectrometry Data Based on O/C Ratio")
# plt.show()


#---------------------------------------------------#
'''
1. 数据预处理
    读取数据：首先，我们从Excel文件中读取了质谱数据。为了演示，选取了前100行数据进行处理。
    特征提取：我们从数据中提取了两组特征：
    元素特征：包括 C, H, O, N, C13, S, P, Cl 等元素的数量，这些特征用于构建节点特征。
    附加特征：包括 O/C, N/C, P/C, S/C, H/C, AImod 等，这些特征用于聚类分析和构建边关系。
2. 使用 KMeans 聚类
    KMeans 聚类：我们使用 KMeans 聚类算法将节点特征按附加特征进行了聚类分析。我们假设数据可以被分成5个簇（可以根据具体问题调整这个参数）。
    聚类结果：聚类算法将每个节点分配到一个簇中，返回的结果是每个节点所属的簇的标识符。
3. 构建图结构
    边的定义：我们定义了图的边，规则是：
    如果两个节点属于同一个簇（即聚类结果相同），则在它们之间创建一条边。这表示在同一簇内的节点是相互连接的。
    图的构建：将节点特征和边结构封装成 PyTorch Geometric 的 Data 对象，适用于图神经网络的进一步处理。
4. 可视化图结构
    转换为 NetworkX 图：将 PyTorch Geometric 的 Data 对象转换为 NetworkX 图对象，以便于利用 NetworkX 提供的可视化工具。
    逐个簇进行可视化：
    针对每个簇，提取对应的子图（即只包含该簇内节点的图）。
    使用 spring_layout 布局算法，这种布局可以更好地展示簇内节点之间的关系。
    分别绘制每个簇的内部结构图，以便详细观察每个簇内部节点的连接关系。
5. 结果分析
    最终我们生成了一系列图形，每个图形展示了一个簇内的节点及其连接关系。这些图形帮助我们更好地理解聚类结果以及同一簇内节点的相互作用。
总结
    这个方法有效地利用了质谱数据中的结构信息，通过聚类分析和图可视化，我们可以直观地观察数据中的模式和关系。通过定义合理的边连接规则，可以进一步提升对数据内在结构的理解，进而为后续的深度学习分析奠定基础。
'''
#---------------------------------------------------#



import torch
import torch_geometric
from torch_geometric.data import Data
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans
from torch_geometric.utils import to_networkx

# 读取数据
df = pd.read_excel(r"water_tu/data/20231128HESI-122_001.xlsx", sheet_name="Result")

# 为了示例，我们只使用前100行数据
df = df.head(100)

# 提取特征，假设前几列为元素数量特征，其他为属性特征
features = df[['C', 'H', 'O', 'N', 'C13', 'S', 'P', 'Cl']].values
additional_features = df[['O/C', 'N/C', 'P/C', 'S/C', 'H/C', 'AImod']].values

# 构建节点特征
node_features = torch.tensor(features, dtype=torch.float)

# 使用KMeans进行聚类
kmeans = KMeans(n_clusters=5, random_state=0)  # 假设我们分成5个簇
clusters = kmeans.fit_predict(additional_features)


# 聚类结果的二维可视化
plt.figure(figsize=(10, 6))
plt.scatter(additional_features[:, 0], additional_features[:, 1], c=clusters, cmap='viridis')
plt.title("KMeans Clustering of Additional Features")
plt.xlabel("O/C Ratio")
plt.ylabel("N/C Ratio")
plt.colorbar(label='Cluster')
plt.show()

# # 选择三个特征进行三维可视化
# fig = plt.figure(figsize=(10, 8))
# ax = fig.add_subplot(111, projection='3d')
# ax.scatter(additional_features[:, 0], additional_features[:, 1], additional_features[:, 2], c=clusters, cmap='viridis')
#
# ax.set_xlabel('O/C Ratio')
# ax.set_ylabel('N/C Ratio')
# ax.set_zlabel('P/C Ratio')
# plt.title("3D KMeans Clustering of Additional Features")
# plt.show()

# 定义边关系，基于聚类结果
edge_index = []
for i in range(len(clusters)):
    for j in range(i + 1, len(clusters)):
        if clusters[i] == clusters[j]:  # 如果属于同一类
            edge_index.append([i, j])
            edge_index.append([j, i])

# 转换为PyTorch张量
edge_index = torch.tensor(edge_index, dtype=torch.long).t().contiguous()

# 构建图数据结构
data = Data(x=node_features, edge_index=edge_index)

# 将图数据转换为 NetworkX 图以进行可视化
G = to_networkx(data, node_attrs=['x'], to_undirected=True)

# 可视化每个簇的内部结构
for cluster_id in set(clusters):
    # 提取属于该簇的节点
    nodes_in_cluster = [i for i in range(len(clusters)) if clusters[i] == cluster_id]

    # 生成该簇的子图
    subgraph = G.subgraph(nodes_in_cluster)

    # 可视化子图
    plt.figure(figsize=(8, 8))
    pos = nx.spring_layout(subgraph)  # 使用spring布局更适合展示内部结构
    nx.draw(subgraph, pos, with_labels=True, node_color='skyblue', node_size=500, font_size=10)
    plt.title(f"Cluster {cluster_id} Internal Structure")
    plt.show()
